HVM patch to add pio IOREQ_WRITE OVERLAP/REPZ support in hvm io.c
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 4 Apr 2006 14:05:17 +0000 (15:05 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 4 Apr 2006 14:05:17 +0000 (15:05 +0100)
hvm_pio_assist().  Also, cleaned up a bit of duplicate code in the
functions.  Simple guest tests (ide pio) pass now for overlapped/rep
write operations.

Signed-off-by: Tom Woller <thomas.woller@amd.com>
Signed-off-by: Mats Petersson <mats.petersson@amd.com>
xen/arch/x86/hvm/io.c

index 893dd68ce5f936eeab93d879400484f7aef42f27..fd9ff611dffcd76346476899cfd31104ca63f74e 100644 (file)
@@ -365,29 +365,42 @@ static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
     unsigned long old_eax;
     int sign = p->df ? -1 : 1;
 
-    if (p->dir == IOREQ_WRITE) {
-        if (p->pdata_valid) {
-            regs->esi += sign * p->count * p->size;
-            if (mmio_opp->flags & REPZ)
-                regs->ecx -= p->count;
-        }
-    } else {
-        if (mmio_opp->flags & OVERLAP) {
-            unsigned long addr;
-
+    if (p->pdata_valid || (mmio_opp->flags & OVERLAP)) {
+        if (mmio_opp->flags & REPZ)
+            regs->ecx -= p->count;
+        if (p->dir == IOREQ_READ) {
             regs->edi += sign * p->count * p->size;
-            if (mmio_opp->flags & REPZ)
-                regs->ecx -= p->count;
 
-            addr = regs->edi;
-            if (sign > 0)
-                addr -= p->size;
-            hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT);
-        } else if (p->pdata_valid) {
-            regs->edi += sign * p->count * p->size;
-            if (mmio_opp->flags & REPZ)
-                regs->ecx -= p->count;
-        } else {
+            if (mmio_opp->flags & OVERLAP) {
+                /* 
+                 * If we are doing in IN and it's overlapping a page boundary, 
+                 * we need to copy the data back to user's page with hvm_copy. 
+                 * Note that overlap * can only be set with paging enabled, so 
+                 * we don't need to worry about * real-mode stuff.  
+                 */
+                unsigned long addr;
+                {
+                    /* 
+                    * We completely ignore segment registers here - 
+                     * it's not a good idea. We also may use upper bits
+                     * in edi when in 16-bit real/protected mode.
+                     * We really need to get the actual address back from
+                     * the arch-dependant HVM portion.
+                     */
+                    struct vcpu *v = current;
+                    if (hvm_realmode(v))
+                        __hvm_bug(regs);
+                }
+                addr = regs->edi;
+                if (sign > 0)
+                    addr -= p->size;
+                hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT);
+            }
+        } else
+            regs->esi += sign * p->count * p->size;
+
+    } else {
+        if (p->dir == IOREQ_READ) {
             old_eax = regs->eax;
             switch (p->size) {
             case 1: